﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Tools;
using Pixysoft.Weblications.Sango.Environment;
using Pixysoft.Weblications.Sango.Battle;

namespace Pixysoft.Weblications.Sango.Formular
{
    class BattleFormular
    {
        public const int default_start_stageindex = 0;

        public const int factor_max_battle = 20;

        public const int default_profession_property = -1;

        /** 默认场景编码 */
        public static int default_scenetype = 1;

        /** 默认道具编码 */
        public static int default_stufftype = 1;

        /// <summary>
        /// 免费军令刷新时间
        /// </summary>
        public static long[] refresh_stage = new long[]
        { 
            DateTimeCoder.Instance.HourToMilliSecond(9),
			DateTimeCoder.Instance.HourToMilliSecond(12)+DateTimeCoder.Instance.MinuteToMilliSecond(30),
            DateTimeCoder.Instance.HourToMilliSecond(19),
			DateTimeCoder.Instance.HourToMilliSecond(21)+DateTimeCoder.Instance.MinuteToMilliSecond(30)
        };


        /// <summary>
        /// 获取战斗属性
        /// </summary>
        /// <returns></returns>
        public static long GetBattlerPointValue(double value)
        {
            return (long)Math.Round(value / 13.889);
        }

        /// <summary>
        /// 每小时增加军令
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public static bool isIncreaseBattleTime(double lastdate)
        {
            DateTime currentdate = GlobalTimer.Instance.GetGlobalTime();

            DateTime headofday = DateTimeCoder.Instance.GetHeadOfToday();

            while (true)
            {
                if (headofday.AddHours(1) > currentdate)
                    break;

                headofday = headofday.AddHours(1);
            }

            return SettingHelper.IsRefresh(GlobalTimer.Instance.ToTimeSequence(headofday), lastdate, DateTimeCoder.Instance.HourToMilliSecond(1));
        }

        /// <summary>
        /// 是否刷新战斗累计
        /// </summary>
        /// <param name="lastdate"></param>
        /// <returns></returns>
        public static bool isNextBattleDay(double lastdate)
        {
            double refreshdate = GlobalTimer.Instance.ToTimeSequence(DateTimeCoder.Instance.GetHeadOfToday()) + PlayerFormular.default_refresh_date;

            return SettingHelper.IsDailyRefresh(refreshdate, lastdate);
        }

        /// <summary>
        /// 是否刷新免费军令
        /// </summary>
        /// <param name="lastdate"></param>
        /// <returns></returns>
        public static bool isFreeBattleRefreshtime(double lastdate)
        {
            long currentdate = GlobalTimer.Instance.ToTimeSequence();

            long head = GlobalTimer.Instance.ToTimeSequence(DateTimeCoder.Instance.GetHeadOfToday());

            foreach (long span in refresh_stage)
            {
                long refreshdate = head + span;

                bool isRefresh = (currentdate >= refreshdate && lastdate < refreshdate);

                if (isRefresh)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// increase free battle count after refresh date.
        /// </summary>
        /// <param name="refreshbattledate"></param>
        /// <returns></returns>
        public static long IncreaseBattleCount(double refreshbattledate)
        {
            return (int)Math.Ceiling((GlobalTimer.Instance.ToTimeSequence() - refreshbattledate) / DateTimeCoder.Instance.HourToMilliSecond(1));
        }

        /// <summary>
        /// 战斗冷却时间
        /// </summary>
        /// <param name="activity"></param>
        /// <returns></returns>
        public static long getBattleCooldownTimespan(Entities.Usr_Activity activity)
        {
            return (long)Math.Round(1000f * 30f + (activity.Usedbattlecount / 3) * 1000f * 30f);
        }




        /// <summary>
        /// 是否命中
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static bool attackHit(Battler attacker, Battler defenser)
        {
            // 攻击命中率

            double x = attacker.HitPointValue;

            // 阵法加成

            x *= attacker.getTacticalAddition().HitPointValue;

            // 防御命中加成

            double y = defenser.DodgePointValue;

            y *= defenser.getTacticalAddition().DodgePointValue;

            double delta = x - y;

            double hitrate = -1;

            if (delta >= BattleConstant.max_hitRate)
            {
                hitrate = BattleConstant.max_hitRate;
            }
            else if (delta <= BattleConstant.min_hitRate)
            {
                hitrate = BattleConstant.min_hitRate;
            }
            else
            {
                hitrate = delta;
            }

            return SettingHelper.RandomNext(100) < hitrate;
        }

        /// <summary>
        /// 普通攻击伤害
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static long attackDamage(Battler attacker, Battler defenser)
        {
            double delta = attacker.AttackPointValue * (1 + attacker.getTacticalAddition().AttackPointValue / 100)
                - defenser.DefensePointValue * (1 + defenser.getTacticalAddition().DefensePointValue / 100);

            double damagefx = 0;

            double totalhpValue = caculateAttackHpvalue(attacker.getLevel());

            if (delta <= 0)
            {
                if (delta <= -420)
                {
                    delta = -420;
                }

                damagefx = delta * (totalhpValue / 4) / -420;
            }
            else
            {
                if (delta >= 280)
                    delta = 280;

                damagefx = delta * (3 * totalhpValue / 4) / 280;
            }

            double professionalDamageFactor = 10 * SysProfessionalRelationHelper.TryGetRelationDamageValue(attacker.getProfessionalSerialCode(), defenser.getProfessionalSerialCode()) / 100;

            double randomDamageFactor = (1f + SettingHelper.RandomNext(5)) / 100f;

            double tacticalDamageFactor = attacker.getTacticalAddition().AttackPointValue;

            return (long)Math.Round(damagefx * (1 + professionalDamageFactor + randomDamageFactor + tacticalDamageFactor));
        }

        /// <summary>
        /// 是否暴击
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static bool attackCritical(Battler attacker, Battler defenser)
        {
            double supposeRate = attacker.CriticalRateValue;

            supposeRate *= attacker.getTacticalAddition().CriticalRateValue;

            return SettingHelper.RandomNext(100) < supposeRate;
        }

        /// <summary>
        /// 是否反击
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static bool defenseCounter(Battler attacker, Battler defenser)
        {
            double supposeRate = defenser.CounterRateValue;

            supposeRate *= defenser.getTacticalAddition().CounterRateValue;

            return SettingHelper.RandomNext(100) < supposeRate;
        }

        /// <summary>
        /// 法术攻击
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static long magicAttackDamage(Battler attacker, Battler defenser)
        {
            double delta = attacker.MagicAttackPointValue * (1 + attacker.getTacticalAddition().MagicAttackPointValue / 100)
                - defenser.MagicDefensePointValue * (1 + defenser.getTacticalAddition().MagicDefensePointValue / 100);

            double damagefx = 0;

            double totalhpValue = caculateAttackHpvalue(attacker.getLevel());

            if (delta <= 0)
            {
                if (delta <= -420)
                {
                    delta = -420;
                }

                damagefx = delta * (totalhpValue / 4) / -420;
            }
            else
            {
                if (delta >= 280)
                    delta = 280;

                damagefx = delta * (3 * totalhpValue / 4) / 280;
            }

            double randomDamageFactor = (1f + SettingHelper.RandomNext(5)) / 100f;

            double tacticalDamageFactor = attacker.getTacticalAddition().AttackPointValue;

            return (long)Math.Round(damagefx * (1 + randomDamageFactor + tacticalDamageFactor));
        }

        /// <summary>
        /// 技能攻击是否命中
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <returns></returns>
        public static bool skillAttackHit(Battler attacker, Battler defenser)
        {
            if (defenser.isFrozen())
                return true;

            return attackHit(attacker, defenser);
        }

        /// <summary>
        /// 技能攻击伤害
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="defenser"></param>
        /// <param name="powerValue"></param>
        /// <returns></returns>
        public static long skillAttackDamage(Battler attacker, Battler defenser, int powerValue)
        {
            double delta = attacker.SkillAttackPointValue * (1 + attacker.getTacticalAddition().SkillAttackPointValue / 100)
          - defenser.SkillDefensePointValue * (1 + defenser.getTacticalAddition().SkillDefensePointValue / 100);

            double damagefx = 0;

            double totalhpValue = caculateAttackHpvalue(attacker.getLevel());

            if (delta <= 0)
            {
                if (delta <= -420)
                {
                    delta = -420;
                }

                damagefx = delta * (totalhpValue / 4) / -420;
            }
            else
            {
                if (delta >= 280)
                    delta = 280;

                damagefx = delta * (3 * totalhpValue / 4) / 280;
            }

            double randomDamageFactor = (1f + SettingHelper.RandomNext(5)) / 100f;

            double tacticalDamageFactor = attacker.getTacticalAddition().AttackPointValue;

            return (long)Math.Round(damagefx * (1 + randomDamageFactor + tacticalDamageFactor));
        }

        /// <summary>
        /// 计算攻击者理想血量
        /// </summary>
        /// <returns></returns>
        private static long caculateAttackHpvalue(double level)
        {
            // 武将血量 + 装备血量

            return (long)Math.Round((200 + level * 50) + (200 * (level / 20) + 10 * level));
        }


    }
}
